from PySide6.QtCore import Signal, QRect
from PySide6.QtGui import QPainter, Qt
from PySide6.QtWidgets import QWidget

from common.build import Build
from common.npc import Npc
from common.world import LatticeMap
from gui.reference import DX, LINE_LENGTH, LW, Pos, xy_to_rc
from gui.signals import SIGNALS
from utils.db import DBSession
from utils.event_bus import EVENT_BUS


class GridWidget(QWidget):
    signal_change_pos = Signal()

    def __init__(self, parent, player):
        super().__init__(parent)
        self.player = player

        self.setFixedSize(LINE_LENGTH + 2, LINE_LENGTH + 2)

    def paintEvent(self, event):
        painter = QPainter(self)
        # 绘制玩家
        x, y = self.player.pos.to_xy()
        rect = QRect(x + LW // 4, y + LW // 4, LW // 2, LW // 2)
        painter.save()
        painter.setPen(Qt.GlobalColor.red)
        painter.setBrush(Qt.GlobalColor.red)
        painter.drawEllipse(rect)
        painter.restore()

        lattice_map: LatticeMap = DBSession.lattice_map[self.player.map_name]
        for i in range(11):
            # horizontal
            painter.drawLine(DX, DX + i * LW, DX + LINE_LENGTH, DX + i * LW)
            # vertical
            painter.drawLine(DX + i * LW, DX, DX + i * LW, DX + LINE_LENGTH)

        for pos, build in lattice_map.builds.items():
            build.draw(painter, Pos(*pos))

        for pos, npc in lattice_map.npc_set.items():
            npc.draw(painter, Pos(*pos))

    def mouseReleaseEvent(self, event):
        pos = event.pos()
        px, py = pos.x(), pos.y()

        if px > DX + LINE_LENGTH or py > DX + LINE_LENGTH:
            return
        pos = Pos(*xy_to_rc((px, py)))
        self.player.pos = pos
        SIGNALS.change_locate.emit()

        local_map: LatticeMap = self.player.get_local_map()
        local_build: Build = local_map.get_build(pos)
        local_npc: Npc = local_map.get_npc(pos)
        if local_npc:
            EVENT_BUS.player_interaction.emit(self.player)

        if event.button() == Qt.MouseButton.RightButton:
            if local_build is not None:
                local_build.interaction(self.player)
            if local_npc is not None:
                local_npc.interaction(self.player)

        self.update()
